package com.huatai.user.controller;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.huatai.common.api.R;
import com.huatai.common.config.MinioAPI;
import com.huatai.common.constant.MinioCommonBucket;
import com.huatai.common.controller.BaseController;
import com.huatai.common.entity.UserInfo;
import com.huatai.common.util.AuthUtil;
import com.huatai.common.util.StringUtil;
import com.huatai.user.constant.MinioBucket;
import com.huatai.user.entity.Role;
import com.huatai.user.entity.User;
import com.huatai.user.service.UserService;
import com.huatai.user.vo.*;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Objects;
import java.util.UUID;


/**
 * @program: ht-system
 * @description: 用户管理控制器
 * @author: songxiude
 * @create: 2023-02-02 15:30
 **/
@Validated
@RestController
@RequestMapping("/user")
@Api(value = "用户管理", tags = "系统用户管理")
public class UserController extends BaseController {
	@Autowired
	private UserService userService;

	@Autowired
	private MinioAPI minioAPI;

	@Autowired
	private StringRedisTemplate redisTemplate;

	@Value("${minio.ENDPOINT}")
	private String minioUrl;

	/**
	 * 用户新增修改
	 *
	 * @param user
	 * @return
	 */
	@PostMapping("/save")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "用户新增修改", notes = "用户新增修改")
	//@PreAuthorize("hasAuthority('user:save')")
	public R userSave(@Valid @RequestBody User user) {
		return R.status(userService.saveUser(user));
	}

	@PostMapping("/delUser")
	@ApiOperation(value = "删除用户", notes = "删除用户")
	//@PreAuthorize("hasAuthority('user:del')")
	public R delUser(@ApiParam(name = "用户id", value = "user_id", required = true) @RequestParam("user_id") Long userId) {
		Assert.isTrue(!Objects.isNull(userId), "删除用户id不能为空");
		return R.status(userService.delUser(userId));
	}

	@PostMapping("/getUserList")
	@ApiOperation(value = "获取用户列表", notes = "获取用户列表")
	@ApiOperationSupport(order = 1, includeParameters = {
		"userParamInfo.account",
		"userParamInfo.phone",
		"userParamInfo.deptId",
		"userParamInfo.page",
		"userParamInfo.size"
	})
	//@PreAuthorize("hasAuthority('user:list')")
	public R getUserList(@RequestBody UserParamInfo userParamInfo) {
		IPage<UserInfoVo> userList = userService.getUserList(userParamInfo);
		return R.data(userList);
	}

	@PostMapping("/getUserRoles")
	@ApiOperation(value = "获取用户角色列表", notes = "获取用户角色列表（前端回显使用）")
	//@PreAuthorize("hasAuthority('user:roles')")
	public R<List<RoleVo>> getUserRoles(@ApiParam(value = "用户id", name = "user_id", required = true)
										@RequestParam("user_id") Long userId) {
		return R.data(userService.getUserRoles(userId));
	}

	@PostMapping("/userRoleAddEdit")
	@ApiOperation(value = "用户角色添加编辑", notes = "用户角色添加编辑")
	//@PreAuthorize("hasAuthority('user:role:edit')")
	public R userRoleAddEdit(@Valid @RequestBody UserRoleParamVo userRoleParamVo) {
		return R.status(userService.userRoleAddEdit(userRoleParamVo));
	}

	@PostMapping("/getUserMenus")
	@ApiOperation(value = "获取用户菜单列表", notes = "获取用户菜单列表")
	//@PreAuthorize("hasAuthority('user:menus')")
	public R getUserMenus() {
		return R.data(userService.getUserPermissions());
	}

	@PostMapping("/userPasswordEdit")
	@ApiImplicitParams({
		@ApiImplicitParam(name = "orig_password", value = "原始密码", required = true),
		@ApiImplicitParam(name = "new_password", value = "新密码", required = true),
		@ApiImplicitParam(name = "affirm_password", value = "确认密码", required = true)
	})
	@ApiOperation(value = "用户修改密码", notes = "用户修改密码")
	//@PreAuthorize("hasAuthority('user:pass:edit')")
	public R userPasswordEdit(@NotBlank(message = "原始密码不能为空") @RequestParam("orig_password") String origPassword,
							  @NotBlank(message = "新密码不能为空") @RequestParam("new_password") String newPassword,
							  @NotBlank(message = "确认密码不能为空") @RequestParam("affirm_password") String affirmPassword) {
		return R.status(userService.userPasswordEdit(origPassword, newPassword, affirmPassword));
	}

	@PostMapping("/userPasswordReset")
	@ApiOperation(value = "用户密码重置", notes = "用户密码重置")
	//@PreAuthorize("hasAuthority('user:pass:reset')")
	public R userPasswordReset(@ApiParam(name = "用户id", value = "user_id", required = true) @RequestParam("user_id") Long userId) {
		return R.status(userService.userPasswordReset(userId));
	}

	@PostMapping("/upload")
	@ApiOperation(value = "共用文件上传", notes = "共用文件上传")
	public R uploadFile(@ApiParam(name = "file", value = "文件上传字段", required = true) MultipartFile file) {
		try {
			DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
			LocalDate now = LocalDate.now();
			String format = now.format(formatter);
			//给文件和图片重新命名
			String fileName = format + "/" + System.currentTimeMillis() + file.getOriginalFilename();
			minioAPI.uploadInputStream(MinioBucket.HUATAI_PUB_BUCKET, fileName, file.getInputStream(), file.getContentType());
			return R.data(fileName);
		} catch (Exception e) {
			return R.fail("文件上传失败");
		}
		//		String signedUrl = minioAPI.getSignedUrl("huatai", fileName, 604800);

	}


	@PostMapping("/downloadFile")
	@ApiOperationSupport(order = 9)
	@ApiOperation(value = "下载文件")
	public void downloadFile(@ApiParam(value = "文件路径", required = true) @RequestParam String url, HttpServletResponse response) {
		//String filePath = url.split(MinioBucket.HUATAI_PUB_BUCKET + "/")[1].split("\\?X")[0];
		String filePath = url;
		try {
			// 获取文件对象
			InputStream object = minioAPI.download(MinioBucket.HUATAI_PUB_BUCKET, filePath);
			byte buf[] = new byte[1024];
			int length = 0;
			response.reset();
			response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filePath.substring(filePath.lastIndexOf("/") + 1), "UTF-8"));
			response.setContentType("application/octet-stream");
			response.setCharacterEncoding("UTF-8");
			OutputStream outputStream = response.getOutputStream();
			// 输出文件
			while ((length = object.read(buf)) > 0) {
				outputStream.write(buf, 0, length);
			}
			// 关闭输出流
			outputStream.close();
		} catch (Exception ex) {
			response.setHeader("Content-type", "text/html;charset=UTF-8");
			String data = "文件下载失败";
			OutputStream ps = null;
			try {
				ps = response.getOutputStream();
				ps.write(data.getBytes("UTF-8"));
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	@PostMapping("/uploadAvatar")
	@ApiOperation(value = "个人头像上传", notes = "个人头像上传")
	public R uploadAvatar(@RequestParam(name = "avatar") String avatar) {
		LambdaUpdateWrapper<User> wrapper = Wrappers.<User>lambdaUpdate();
		wrapper.eq(User::getId, AuthUtil.getUser().getUserId()).set(User::getAvatar, avatar);
		boolean update = userService.update(null, wrapper);
		if (!update){
			return R.fail("头像更新失败");
		}
		String aurl = minioUrl + "/" + MinioCommonBucket.HUATAI_PUB_BUCKET + "/" + avatar;
		return R.data(aurl);
	}

	@PostMapping("/cutSkin")
	@ApiOperation(value = "用户皮肤切换", notes = "用户皮肤切换")
	@ApiImplicitParam(name = "skin", value = "皮肤1深色2浅色", required = true)
	public R cutSkin(@RequestParam(name = "skin") Integer skin) {
		LambdaUpdateWrapper<User> wrapper = Wrappers.lambdaUpdate();
		wrapper.eq(User::getId, AuthUtil.getUser().getUserId()).set(User::getSkin, skin);
		boolean update = userService.update(null, wrapper);
		return R.status(update);
	}

	@GetMapping("/logout")
	@ApiOperation(value = "用户登出", notes = "用户登出")
	public R logout() {
		UserInfo user = AuthUtil.getUser();
		if (user != null) {
			redisTemplate.delete("ht:token:" + user.getUserId());
		}
		return R.success("退出系统成功");
	}
}
